<!--
 * @Description: 用于可拖拽调整的框架组件，以代替ejs-splitter，参考：https://www.kancloud.cn/cyyspring/vuejs/957699
-->
<template>
  <div class="split-pane-wrapper" ref="outer">
    <slot :is="PaneItem"></slot>
    <div v-for="i in childrenSplitSize" :key="i" class="pane-trigger-con" @mousedown="handleMousedown($event,i)" ref="trigger" :style="getTriggerStyle(i)"></div>
  </div>
</template>
  <script>
  import PaneItem from './PaneItem.vue'
  export default {
    name: 'SplitPane',
    components: {
      PaneItem
    },
    props: {
      orientation:{//方向，可取值Horizontal或Vertical
        type: String,
        default: 'Horizontal'
      },
      value: {
        type: Number,
        default: 0.5
      },
      triggerSize: {
        type: Number,
        default: 3
      }
    },
    data () {
      return {
        // leftOffset: 0.3,
        canMove: false,
        moveTriggerIndex: -1,
        initOffset: 0,
        spanCount: 0 ,
        spanArray:[],
        childrenSplitSize: 0,
      }
    },
    beforeMount(){

    },
    mounted(){
      const outerRect = this.$refs.outer.getBoundingClientRect()

      let _this=this;
      _this.childrenSplitSize = this.$children.length-1;
      let fixedSpanArray=[]
      for(let i=0;i<this.$children.length;i++){
        let paneItem = this.$children[i];
        if(paneItem.span>0)
        {
          _this.spanArray.push({span:paneItem.span,index:i});
          _this.spanCount += paneItem.span
        }else if(this.isHorizontal){
          let element = paneItem.$refs.paneItem;
          if(element.getBoundingClientRect().width>0){
            let parent = outerRect.width
            let  child = element.getBoundingClientRect().width;
            fixedSpanArray.push({span:child/parent,index:i});
          }
        }else if(!this.isHorizontal){
          let element = paneItem.$refs.paneItem;
          if(element.getBoundingClientRect().height>0){
            let parent = outerRect.height
            let  child = element.getBoundingClientRect().height;
            fixedSpanArray.push({span:child/parent,index:i});
          }
        }
      }
      //剩余的部分使用span来计算比例
      let countLeft=1;
      fixedSpanArray.forEach((t)=>{
        countLeft -= t.span;
      })
      this.spanArray.forEach((t)=>{
        t.span = t.span/_this.spanCount * countLeft;
      })
      this.spanArray.push(...fixedSpanArray);
      this.spanArray.sort((a,b)=>{
        return a.index - b.index;
      })

      // console.log('_this.spanCount',_this.spanCount,this.spanArray,fixedSpanArray)
      let count=0;
      for(let i=0;i<this.spanArray.length;i++){
        _this.$children[this.spanArray[i].index].start = count;
        _this.$children[this.spanArray[i].index].end = (count+_this.spanArray[i].span)
        _this.$children[this.spanArray[i].index].index = i;
        count += _this.spanArray[i].span;
      }
    },
    computed: {
      leftOffsetPercent () {
        return `${this.value * 100}%`
      },
      rightOffsetPercent(){
        return `${(1 - this.value) * 100}%`
      },
      triggerLeft () {
        return `calc(${this.value * 100}% - ${this.triggerSize / 2}px)`
      },
      isHorizontal(){
        return this.orientation.toLowerCase() === 'horizontal'
      }
    },
    methods: {
      handleClick () {
        this.leftOffset -= 0.02
      },
      handleMousedown (event,i) { 
        this.moveTriggerIndex = i;        
        document.addEventListener('mousemove', this.handleMousemove)
        document.addEventListener('mouseup', this.handleMouseup)
        if(this.isHorizontal){
          this.initOffset = event.pageX - event.srcElement.getBoundingClientRect().left
        }else{
          this.initOffset = event.pageY - event.srcElement.getBoundingClientRect().top
        }
        this.canMove = true
        this.$emit("resizeStart")
      },
      handleMousemove (event) {
        if (!this.canMove) return
        let index = this.moveTriggerIndex;
        let min = this.getFixMinMax(this.$children[index-1],true) ;
        let max = this.getFixMinMax(this.$children[index],false);
        if(this.isHorizontal){
          const outerRect = this.$refs.outer.getBoundingClientRect()
          let offsetPercent = (event.pageX - this.initOffset + this.triggerSize / 2 - outerRect.left) / outerRect.width
          if (offsetPercent < min) offsetPercent = min;
          if (offsetPercent > max) offsetPercent = max;
          this.$children[index-1].end = offsetPercent;
          this.$children[index].start = offsetPercent;
          // this.$emit('input', offsetPercent)
          // this.$emit('update:value', offsetPercent)
        }else{          
          const outerRect = this.$refs.outer.getBoundingClientRect()
          let offsetPercent = (event.pageY - this.initOffset + this.triggerSize / 2 - outerRect.top) / outerRect.height
          if (offsetPercent < min) offsetPercent = min
          if (offsetPercent > max) offsetPercent = max
          this.$children[index-1].end = offsetPercent;
          this.$children[index].start = offsetPercent;
          // this.$emit('input', offsetPercent)
          // this.$emit('update:value', offsetPercent)
        }
      },
      //该函数用于计算最小和最大的值，需要考虑设置的最大限定值、最小 
      getFixMinMax(child,isMin)
      {
        let length = this.getOuterLength();
        if(isMin){
          if(child.min.endsWith('px')){
            return child.start + parseFloat(child.min)/length;
          }else if(child.min.endsWith('%'))
          {
            return child.start + parseFloat(child.min)/100;
          }else{
            return child.start;
          }              
        }else{
          if(child.min.endsWith('px')){
            return child.end - parseFloat(child.min)/length;
          }else if(child.min.endsWith('%'))
          {
            return child.end + parseFloat(child.min)/100;
          }else{
            return child.end;
          }  
        }  
      },
      getOuterLength(){
        const outerRect = this.$refs.outer.getBoundingClientRect();
        let length = 0;
        if(this.isHorizontal){
          length = outerRect.width;
        }else{
          length = outerRect.height;
        }
        return length;
      },
      getRectLength(rect){
        if(this.isHorizontal){
          return rect.width;
        }else{
          return rect.height;
        }
      },
      handleMouseup () {
        this.canMove = false
        this.moveTriggerIndex = -1;
        document.removeEventListener('mousemove', this.handleMousemove)
        document.removeEventListener('mouseup', this.handleMouseup)
        this.$emit("resizeStop")
      },
      getTriggerStyle(i){
        if(this.isHorizontal){
          return { left: `${this.$children[i-1].end*100}%`, width: `${this.triggerSize}px`, cursor: 'col-resize',height: '100%'}
        }else{//纵向
          return { top: `${this.$children[i-1].end*100}%`, height: `${this.triggerSize}px`, cursor: 'row-resize',width: '100%'}
        }
      },
      //改变第index个面板的宽度或高度
      collapse(index){        
        const length = this.getOuterLength();
        const naborIndex = (index==(this.$children.length-1)?(index-1):index+1);
        const size = this.$children[index].collapsedSize;
        if(this.$children[naborIndex] && this.$children[index]){//相邻的元素都有值才会操作
          const oriLength = this.getRectLength(this.$children[index].$refs.paneItem.getBoundingClientRect());          
          this.$children[index].isCollapsed = true;
          const offsetLength = parseFloat(size)  - oriLength;
          const offsetSpan = offsetLength/length;
          if(naborIndex>index){
              this.$children[index].originSpan = this.$children[index].end;
              this.$children[index].originNaborSpan = this.$children[naborIndex].start;
              this.$children[index].end = this.$children[index].end + offsetSpan;
              this.$children[naborIndex].start = this.$children[naborIndex].start + offsetSpan;
          }else{
              this.$children[index].originSpan = this.$children[index].start;
              this.$children[index].originNaborSpan = this.$children[naborIndex].end;
              this.$children[index].start = this.$children[index].start + offsetSpan;
              this.$children[naborIndex].end = this.$children[naborIndex].end + offsetSpan;
          }         
        }
      },
      expand(index){
        const naborIndex = (index==(this.$children.length-1)?(index-1):index+1);
        this.$children[index].isCollapsed = false;
        if(this.$children[naborIndex] && this.$children[index]){//相邻的元素都有值才会操作
          const paneItem = this.$children[index];
          const originSpan = paneItem.originSpan;
          const originNaborSpan = paneItem.originNaborSpan;
          if(naborIndex>index){
              this.$children[index].end = originSpan;
              this.$children[naborIndex].start = originNaborSpan;
          }else{
              this.$children[index].start = originNaborSpan;
              this.$children[naborIndex].end = originNaborSpan;
          }         
        }
      },
      isCollapsed(index){
        return this.$children[index].isCollapsed;
      }
    }
  }
  </script>
  <style scoped>
  .split-pane-wrapper {
      width: 100%;
      height: 100%;
      position: relative;
  }

  .split-pane-wrapper>.pane {
      position: absolute;
  }
  
  .pane-left {
      position: absolute;
      background-color: palevioletred;
  }

  .pane-right {
      position: absolute;
      background-color: paleturquoise;
  }

  .pane-trigger-con {
      border: 1px solid #ccc;
      position: absolute;
      z-index: 10;
      user-select: none;
  }
  .pane-item{
    position:absolute;
  }
</style>